﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Games.ChallengeMemory
{
    class Game
    {
        public int Size { get; private set; }
        public int TCount { get; private set; }
        public int Frame { get; private set; }
        public bool IsOver { get; private set; }
        public bool IsRunning { get; private set; }

        private List<int> LastTargets = new List<int>();

        private List<int> CurrentTargets = new List<int>();

        public void Init(int size, int tcount)
        {
            this.IsOver = false;
            this.IsRunning = false;
            this.Size = size;
            this.Frame = -2;
            this.LastTargets.Clear();
            this.CurrentTargets.Clear();
            this.TCount = 1;
            this.Tick();
            this.TCount = tcount;
            this.Tick();
        }

        public List<int> GetLast()
        {
            return LastTargets.ToList();
        }
        public List<int> GetCurrent()
        {
            return CurrentTargets.ToList();
        }

        public async Task Send(int id, Func<Task> warn, Func<int, Task> flash)
        {
            if(this.IsOver)
            {
                return;
            }
            if(!this.IsRunning)
            {
                this.IsRunning = true;
            }
            if(this.LastTargets.Contains(id))
            {
                this.LastTargets.Remove(id);
                await flash(id);
            }
            else
            {
                await warn();
                this.IsOver = true;
            }
            if(this.LastTargets.Count == 0)
            {
                this.Tick();
            }
        }

        private void Tick()
        {
            LastTargets = CurrentTargets.ToList();
            CurrentTargets.Clear();
            this.Frame++;
            var rd = new Random(DateTime.Now.Millisecond);

            //一个目标就随便生成，只要不与上次一样就行
            if(TCount == 1)
            {
                while(CurrentTargets.Count < TCount)
                {
                    var x = rd.Next(Size * Size);
                    if(!LastTargets.Contains(x) && !CurrentTargets.Contains(x))
                    {
                        CurrentTargets.Add(x);
                    }
                }
            }
            //多个目标，先找一个不在之前的行和列的点，在此点同行或同列选择其他点，即每次生成都是同行或同列
            else
            {
                var cols = LastTargets.Select(i => i % Size).ToList();
                var rows = LastTargets.Select(i => i / Size).ToList();
                int x = -1;
                while(true)
                {
                    x = rd.Next(Size * Size);
                    if(!cols.Contains(x % Size) && !rows.Contains(x / Size))
                    {
                        break;
                    }
                }
                CurrentTargets.Add(x);
                var isOnRow = rd.Next(Size * Size * 2) % 2 == 1;
                var v = isOnRow ? x / Size : x % Size;
                while(CurrentTargets.Count < TCount)
                {
                    var h = rd.Next(Size);
                    var xx = isOnRow ? v * Size + h : h * Size + v;
                    if(!CurrentTargets.Contains(xx))
                    {
                        CurrentTargets.Add(xx);
                    }
                }
            }
        }
    }
}
